<!-- 字典 -->
<template>
  <div class="app-container">
	<div class="app-layout">
		<!-- 左侧字典树 -->
		<div class="left">
			<DictTree ref="dictTreeRef" v-model="queryParams.dictId" @node-click="handleTreeNodeClick" />
		</div>

		<!-- 右侧字典项列表 -->
		<div class="right">
			<div class="pane">
				<div class="head" style="padding-right: 8px;">
					<div class="head-title">
						<span>字典项列表</span>
						<template v-if="currentDict">
							<el-divider direction="vertical" />
							<span class="current-dict">{{ currentDict.name }}</span>
						</template>
					</div>
					<div style="flex: 1;"></div>
					<div>
						<el-button
							type="primary"
							icon="plus"
							:disabled="!currentDict"
							@click="handleAddDictItem"
							size="small"
						>
							新增
						</el-button>
						<el-button
							type="danger"
							icon="delete"
							:disabled="selectIds.length === 0"
							@click="handleDeleteDictItem()"
							size="small"
						>
							删除
						</el-button>
					</div>
				</div>
				<div class="body">
					<div class="table-tool-bar">
<!-- 						<div>
							<el-button
								type="primary"
								icon="plus"
								:disabled="!currentDict"
								@click="handleAddDictItem"
							>
								新增
							</el-button>
							<el-button
								type="danger"
								icon="delete"
								:disabled="selectIds.length === 0"
								@click="handleDeleteDictItem()"
							>
								删除
							</el-button>
						</div> -->
						<div>
							<el-input
								v-model="queryParams.keywords"
								style="width:320px"
								placeholder="输入字典项名称或值进行搜索"
								class="input-with-select"
							>
								<template #append>
									<el-button icon="search" @click="loadDictItems" />
								</template>
							</el-input>
						</div>
					</div>

					<div>
						<el-table
							v-loading="itemLoading"
							:data="dictItemList"
							border
							height="calc(100vh - 260px)"
							@selection-change="handleSelectionChange"
						>
							<el-table-column type="selection" width="50" align="center" />
							<el-table-column label="字典项名称" prop="name" />
							<el-table-column label="字典项值" prop="value" width="120" />
							<el-table-column label="排序" prop="sort" width="80" />
							<el-table-column label="状态" prop="status" width="120">
								<template #default="scope">
									<el-tag :type="scope.row.status === '1' ? 'success' : 'info'">
										{{ scope.row.status === '1' ? '启用' : '禁用' }}
									</el-tag>
								</template>
							</el-table-column>
							<el-table-column label="操作" fixed="right" width="150">
								<template #default="scope">
									<el-button
										type="primary"
										link
										icon="edit"
										size="small"
										@click="handleEditDictItem(scope.row)"
									>
										编辑
									</el-button>
									<el-button
										type="danger"
										link
										icon="delete"
										size="small"
										@click="handleDeleteDictItem(scope.row.id)"
									>
										删除
									</el-button>
								</template>
							</el-table-column>
						</el-table>

						<pagination
							v-model:total="itemTotal"
							v-model:page="itemQueryParams.cur"
							v-model:limit="itemQueryParams.limit"
							@pagination="loadDictItems"
						/>
					</div>
				</div>
			</div>
		</div>
	</div>

    <!-- 字典表单弹窗 -->
    <el-drawer
      v-model="dictDialog.visible"
      :title="dictDialog.title"
      append-to-body
      @close="handleCloseDictDialog"
      :close-on-click-modal="false"
    >
      <el-form ref="dictFormRef" :model="dictForm" :rules="dictRules" label-width="80px">
        <el-form-item label="上级字典" prop="parentId">
          <el-tree-select
            v-model="dictForm.parentId"
            :data="dictTreeData"
            :props="{
              label: 'name',
              value: 'id',
              children: 'children'
            }"
            placeholder="请选择上级字典"
            check-strictly
            default-expand-all
            :render-after-expand="false"
          />
        </el-form-item>
        <el-form-item label="字典名称" prop="name">
          <el-input v-model="dictForm.name" placeholder="请输入字典名称" />
        </el-form-item>
        <el-form-item label="字典编码" prop="code">
          <el-input v-model="dictForm.code" placeholder="请输入字典编码" />
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="dictForm.status">
            <el-radio label="1" :value="'1'">启用</el-radio>
            <el-radio label="0" :value="'0'">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div style="flex: auto">
          <el-button @click="handleCloseDictDialog">取消</el-button>
          <el-button type="primary" @click="handleSubmitDict">确定</el-button>
        </div>
      </template>
    </el-drawer>

    <!-- 字典项表单弹窗 -->
    <el-drawer
      v-model="itemDialog.visible"
      :title="itemDialog.title"
      append-to-body
      @close="handleCloseItemDialog"
      :close-on-click-modal="false"
    >
      <el-form ref="itemFormRef" :model="itemForm" :rules="itemRules" label-width="120px">
        <el-form-item label="字典项名称" prop="name">
          <el-input v-model="itemForm.name" placeholder="请输入字典项名称" />
        </el-form-item>

        <el-form-item label="字典项值" prop="value">
          <el-input v-model="itemForm.value" placeholder="请输入字典项值" />
        </el-form-item>

        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="itemForm.status">
            <el-radio label="1" :value="'1'">启用</el-radio>
            <el-radio label="0" :value="'0'">禁用</el-radio>
          </el-radio-group>
        </el-form-item>

        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="itemForm.sort" :min="0" />
        </el-form-item>

        <el-form-item label="备注" prop="remark">
          <el-input
            v-model="itemForm.remark"
            type="textarea"
            placeholder="请输入备注"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div style="flex: auto">
          <el-button @click="handleCloseItemDialog">取消</el-button>
          <el-button type="primary" @click="handleSubmitItem">确定</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue';
import type { FormInstance } from 'element-plus';
import { ElMessage, ElMessageBox } from 'element-plus';
import DictTree from './components/DictTree.vue';
import DictAPI, { type Dict, type DictItem } from '@/api/system/dict';
import {recurOptions} from "@/utils/TreeUtil";
// 查询参数
const queryParams = reactive({
  keywords: '',
  dictId: '',
  cur: 1,
  limit: 10
});

// 字典项查询参数
const itemQueryParams = reactive({
  keywords: '',
  dictId: '',
  cur: 1,
  limit: 10
});

// 当前选中的字典
const currentDict = ref<Dict>();

// 字典项列表数据
const dictItemList = ref<DictItem[]>([]);
const itemTotal = ref(0);
const itemLoading = ref(false);
const selectIds = ref<string[]>([]);

// 字典表单
const dictDialog = reactive({
  visible: false,
  title: ''
});

const dictFormRef = ref<FormInstance>();
const dictForm = reactive<any>({
  id: '',
  name: '',
  code: '',
  status: '1',
  parentId: '-1'
});

const dictRules = {
  parentId: [{ required: true, message: '请选择上级字典', trigger: 'change' }],
  name: [{ required: true, message: '请输入字典名称', trigger: 'blur' }],
  code: [{ required: true, message: '请输入字典编码', trigger: 'blur' }]
};

// 添加父级选择验证
const validateParentId = (rule: any, value: string, callback: Function) => {
  if (dictForm.id && value === dictForm.id) {
    callback(new Error('上级字典不能选择自己'));
  } else {
    callback();
  }
};

// 字典树数据
const dictTreeData = ref<any[]>([]);

// 字典树组件的 ref
const dictTreeRef = ref();

// 加载字典树数据
const loadDictTreeData = async () => {
  const data = await DictAPI.getTree('');
  // 添加顶级节点
  dictTreeData.value = [{
    id: '-1',
    name: '顶级字典',
    code: '',
    parentId: '',
    children: recurOptions(data,'-1')
  }];
};

// 处理树节点点击
const handleTreeNodeClick = (data: any) => {
  if (data.type === 'add') {
    handleAddDict();
  } else if (data.type === 'edit') {
    handleEditDict(data.data);
  } else if (data.type === 'delete') {
    handleDeleteDict(data.data.id);
  } else {
    currentDict.value = data;
    itemQueryParams.dictId = data.id;
    itemQueryParams.cur = 1;
    loadDictItems();
  }
};

// 加载字典项列表
const loadDictItems = () => {
  if (!currentDict.value) return;
  
  itemLoading.value = true;
  DictAPI.getItemPage(itemQueryParams)
    .then((data: any) => {
      dictItemList.value = data.list;
      itemTotal.value = data.totalRow;
    })
    .finally(() => {
      itemLoading.value = false;
    });
};

// 表格多选
const handleSelectionChange = (selection: DictItem[]) => {
  selectIds.value = selection.map(item => item.id);
};

// 新增字典项
const handleAddDictItem = () => {
  itemDialog.visible = true;
  itemDialog.title = '新增字典项';
  itemForm.id = '';
  itemForm.dictId = currentDict.value?.id || '';
};

// 编辑字典项
const handleEditDictItem = (row: DictItem) => {
  itemDialog.visible = true;
  itemDialog.title = '编辑字典项';
  Object.assign(itemForm, row);
};

// 删除字典项
const handleDeleteDictItem = async (id?: string) => {
  const ids = [id || selectIds.value].join(',');
  if (!ids) {
    ElMessage.warning('请选择要删除的数据');
    return;
  }

  try {
    await ElMessageBox.confirm('确认删除选中的字典项？', '提示', {
      type: 'warning'
    });
    await DictAPI.deleteItem(ids);
    ElMessage.success('删除成功');
    loadDictItems();
  } catch (err) {
    if (err !== 'cancel') {
      console.error(err);
    }
  }
};

// 提交字典项表单
const handleSubmitItem = async () => {
  if (!itemFormRef.value) return;
  
  try {
    await itemFormRef.value.validate();
    await DictAPI.saveItem(itemForm);
    ElMessage.success(itemForm.id ? '修改成功' : '新增成功');
    handleCloseItemDialog();
    loadDictItems();
  } catch (err) {
    console.error(err);
  }
};

// 关闭字典项弹窗
const handleCloseItemDialog = () => {
  itemDialog.visible = false;
  itemFormRef.value?.resetFields();
};

// 新增字典
const handleAddDict = () => {
  dictDialog.visible = true;
  dictDialog.title = '新增字典';
  dictForm.id = '';
  dictForm.parentId = '-1';
  // 加载树形数据
  loadDictTreeData();
};

// 编辑字典
const handleEditDict = async (row: Dict) => {
  dictDialog.visible = true;
  dictDialog.title = '编辑字典';
  // 加载树形数据
  await loadDictTreeData();
  // 设置表单数据
  Object.assign(dictForm, row);
};

// 删除字典
const handleDeleteDict = async (id: string) => {
  try {
    await ElMessageBox.confirm('确认删除该字典吗？', '提示', {
      type: 'warning'
    });
    await DictAPI.deleteByIds(id);
    ElMessage.success('删除成功');
    // 重新加载树
    await loadTree();
  } catch (err) {
    if (err !== 'cancel') {
      console.error(err);
    }
  }
};

// 提交字典表单
const handleSubmitDict = async () => {
  if (!dictFormRef.value) return;
  
  // 验证父级选择
  if (dictForm.id && dictForm.parentId === dictForm.id) {
    ElMessage.error('上级字典不能选择自己');
    return;
  }
  
  try {
    await dictFormRef.value.validate();
    await DictAPI.save(dictForm);
    ElMessage.success(dictForm.id ? '修改成功' : '新增成功');
    handleCloseDictDialog();
    // 重新加载树
    await loadTree();
  } catch (err) {
    console.error(err);
  }
};

// 关闭字典弹窗
const handleCloseDictDialog = () => {
  dictDialog.visible = false;
  dictFormRef.value?.resetFields();
};

// 字典项表单
const itemDialog = reactive({
  visible: false,
  title: ''
});

const itemFormRef = ref<FormInstance>();
const itemForm = reactive<DictItem>({
  id: '',
  dictId: '',
  name: '',
  value: '',
  status: '1',
  sort: 0,
  remark: ''
});

// 字典项表单校验规则
const itemRules = {
  name: [{ required: true, message: '请输入字典项名称', trigger: 'blur' }],
  value: [{ required: true, message: '请输入字典项值', trigger: 'blur' }]
};

// 加载树
const loadTree = async () => {
  await dictTreeRef.value?.loadTree();
};

onMounted(() => {
  // 初始加载
});
</script>

<style lang="scss" scoped>
.left {
  width: 280px;
  margin-right: 10px;
}

.right {
  width: calc(100% - 290px);
}

.table-tool-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 5px;
}

:deep(.el-table th.el-table__cell) {
  background-color: #fafafa;
  background-image: linear-gradient(to bottom, #f2f2f2 0, #fafafa 100%);
}

.head-title {
  display: flex;
  align-items: center;
  
  .current-dict {
    color: var(--el-color-primary);
    font-weight: bold;
  }
}

:deep(.el-divider--vertical) {
  margin: 0 8px;
  height: 14px;
}
</style>